Skip to content

fix(desktop,web): bump @xterm/* to beta.289 line for shared-atlas garble fix - #5701

Merged
AviPeltz merged 2 commits into
mainfrom
fix-xterm-shared-atlas-garble
Jul 16, 2026
Merged

AviPeltz merged 2 commits into
mainfrom
fix-xterm-shared-atlas-garble

Conversation

@AviPeltz

@AviPeltz AviPeltz commented Jul 15, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Terminal panes intermittently render garbled multicolor glyph fragments (layout intact, text unreadable), typically after heavy scrolling through colorful TUI output (Claude Code). Copying the garbled region yields correct text — the buffer is fine, the WebGL renderer is drawing from wrong texture-atlas positions.

Root cause (upstream)

xterm.js shares one WebGL glyph texture atlas across all terminals with the same font/theme/DPR — which is every pane in Superset, including parked/reused runtimes. When glyph churn triggers an atlas page merge in one terminal, the invalidation signal was a consume-once flag: the first renderer to call beginFrame() ate it and rebuilt its model; every sibling renderer kept stale glyph→texture coordinates and drew garbage.

Same class of bug we bumped for once before (#4892/#4893).

Changes

  • Bump all @xterm/* deps to the beta.289 release line across apps/desktop, apps/web, packages/shared, packages/host-service (addon-webgl pairs at beta.288 — its numbering trails core by one, same as our previous 219/220 pin)
  • bunfig.toml: scoped minimumReleaseAgeExcludes for @xterm/* only — the release is 1 day old and inside our 3-day supply-chain gate. Versions are pinned exact; the exclusion is dated and safe to remove after 2026-07-16.

Verification

  • bun run typecheck — green (35 tasks; the one docs failure was stale fumadocs codegen in a fresh worktree, passes on re-run)
  • bun run lint — clean
  • packages/shared wheel-handler + identity-coupling tests: 26 pass
  • packages/host-service terminal tests (@xterm/headless consumer): 88 pass

Note: the upstream issue lists a second, still-unfixed failure mode (atlas page-cap overflow → render-loop exception). This PR addresses the garbling; worth tracking upstream PR 2 of the split.


Open in Stage

Summary by cubic

Bump @xterm/* to the beta.289 line to pick up the shared WebGL glyph atlas fix, removing garbled multicolor text after heavy scrolling. Applies to desktop and web terminals.

  • Dependencies
    • @xterm/xterm → 6.1.0-beta.289, @xterm/addon-webgl → 0.20.0-beta.288; align other @xterm/* to beta.289 across desktop, web, shared, and host-service, except @xterm/addon-ligatures which stays at 0.11.0-beta.220 due to a Vite build issue (node:diagnostics_channel).
    • Add dated minimumReleaseAgeExcludes for @xterm/* in bunfig.toml to allow these releases; remove after 2026-07-16.

Written for commit fbb89b9. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Maintenance
    • Updated terminal components and extensions to newer XTerm releases across the desktop, web, and shared application experiences.
    • Improved package installation handling for the updated terminal components.
    • No new user-facing features or workflow changes were introduced.

…ble fix

Terminals sharing a WebGL texture atlas (same font/theme/DPR — all of ours)
rendered garbled multicolor glyph fragments after another terminal triggered
an atlas page merge: the consume-once invalidation flag was eaten by the
first renderer to draw, leaving siblings with stale glyph->texture coords.

Fixed upstream in xtermjs/xterm.js#6042 (per-renderer pageLayoutVersion),
first shipped in xterm 6.1.0-beta.289 / addon-webgl 0.20.0-beta.288.

The versions published 2026-07-13, inside the 3-day minimumReleaseAge
window, so bunfig.toml gets a scoped, dated exclusion for @xterm/* only.
@ghost

ghost commented Jul 15, 2026 •

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 3 individual chapters for you:

Title
1 Allow recent @xterm releases in Bun config
2 Bump xterm dependencies across the workspace
3 Other changes
Open in Stage

Chapters generated by Stage for commit fbb89b9 on Jul 15, 2026 6:35am UTC.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Xterm dependencies are upgraded across desktop, web, host-service, and shared workspace manifests. Bun installation settings now exclude the pinned xterm packages from minimum release-age enforcement.

Changes

xterm dependency alignment

Layer / File(s) Summary
Update xterm version pins
apps/desktop/package.json, apps/web/package.json, packages/host-service/package.json, packages/shared/package.json
Xterm addons, headless, and terminal dependencies are updated from earlier beta releases to newer beta.289/beta.288 versions.
Configure xterm release-age exclusions
bunfig.toml
Adds minimumReleaseAgeExcludes entries for the listed @xterm/* packages.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is conventional, concise, and accurately summarizes the xterm dependency bump and its garbled-text fix.
Description check ✅ Passed The description covers the problem, root cause, changes, and verification, though it does not follow the template headings exactly.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-xterm-shared-atlas-garble

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Bumps all @xterm/* packages from the beta.220 release line to beta.289 (core/addons) and beta.288 (addon-webgl) across apps/desktop, apps/web, packages/host-service, and packages/shared, targeting the upstream fix for garbled WebGL glyph rendering caused by a consume-once invalidation flag on the shared texture atlas.

  • All 11 @xterm/* packages are updated consistently; addon-webgl intentionally trails by one version matching the previous 219/220 pattern.
  • A minimumReleaseAgeExcludes entry in bunfig.toml bypasses the 3-day supply-chain gate for these fresh packages (published 2026-07-13), with an inline comment to remove it after 2026-07-16.
  • The lock file includes notable transitive dependency changes driven by @xterm/addon-ligatures@beta.289: opentype.js jumps from 0.8.0 to 2.0.0 and lru-cache (scoped to the addon) from 6.0.0 to 11.5.2.

Confidence Score: 4/5

Safe to merge; the changes are exact-pinned dep bumps with a clear upstream fix, verified by typecheck and the existing test suites.

All package changes are exact-pinned and the entire bump is motivated by a well-documented upstream fix. The supply-chain gate bypass in bunfig.toml is time-boxed but has no automated cleanup enforcement. The transitive opentype.js 0.8.0→2.0.0 and lru-cache 6→11 upgrades inside @xterm/addon-ligatures are unlikely to surface, but they are the kinds of silent changes that can affect ligature rendering in edge cases without breaking typecheck.

bunfig.toml — the minimumReleaseAgeExcludes block should be removed after 2026-07-16. bun.lock — verify ligature rendering after the opentype.js 2.x transitive upgrade if ligature-heavy fonts are in use.

Important Files Changed

Filename Overview
bunfig.toml Adds minimumReleaseAgeExcludes to bypass the 3-day supply-chain gate for all @xterm/* packages; comment instructs removal after 2026-07-16 but no automated enforcement exists
apps/desktop/package.json Bumps all 11 @xterm/* deps from beta.220/beta.219 to beta.289/beta.288; the webgl addon trailing by one is intentional and consistent with the prior pin pattern
apps/web/package.json Bumps @xterm/addon-fit and @xterm/xterm from beta.220 to beta.289; consistent with desktop update
packages/host-service/package.json Bumps @xterm/headless from beta.220 to beta.289; the headless consumer's 88-test suite reportedly passes
packages/shared/package.json Bumps @xterm/xterm devDependency from beta.220 to beta.289 for type-checking the shared package
bun.lock Lock file reflects all @xterm/* bumps; also pulls in notable transitive dep changes: opentype.js 0.8.0→2.0.0 and lru-cache 6→11 (both via @xterm/addon-ligatures), and yallist top-level 4→5; tiny-inflate removed

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["@xterm/xterm 6.1.0-beta.289\n(core renderer + shared atlas)"] --> B["Shared WebGL Glyph Atlas\n(pageLayoutVersion — monotonic)"]
    B --> C["Renderer A\n(Terminal Pane 1)"]
    B --> D["Renderer B\n(Terminal Pane 2)"]
    B --> E["Renderer N\n(Parked / Reused Runtime)"]
    C -->|"beginFrame(): reads pageLayoutVersion"| F{Version changed?}
    D -->|"beginFrame(): reads pageLayoutVersion"| F
    E -->|"beginFrame(): reads pageLayoutVersion"| F
    F -->|"Yes → rebuild glyph model"| G["✅ Correct texture coordinates"]
    F -->|"No → reuse cached model"| G

    subgraph "Before beta.220 — consume-once flag"
        X["Atlas page merge fires"] --> Y["Flag set once"]
        Y --> Z["First renderer consumes flag → rebuilt"]
        Z --> AA["Siblings keep stale coords → garbled glyphs"]
    end

    subgraph "After beta.289 — monotonic pageLayoutVersion"
        B
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["@xterm/xterm 6.1.0-beta.289\n(core renderer + shared atlas)"] --> B["Shared WebGL Glyph Atlas\n(pageLayoutVersion — monotonic)"]
    B --> C["Renderer A\n(Terminal Pane 1)"]
    B --> D["Renderer B\n(Terminal Pane 2)"]
    B --> E["Renderer N\n(Parked / Reused Runtime)"]
    C -->|"beginFrame(): reads pageLayoutVersion"| F{Version changed?}
    D -->|"beginFrame(): reads pageLayoutVersion"| F
    E -->|"beginFrame(): reads pageLayoutVersion"| F
    F -->|"Yes → rebuild glyph model"| G["✅ Correct texture coordinates"]
    F -->|"No → reuse cached model"| G

    subgraph "Before beta.220 — consume-once flag"
        X["Atlas page merge fires"] --> Y["Flag set once"]
        Y --> Z["First renderer consumes flag → rebuilt"]
        Z --> AA["Siblings keep stale coords → garbled glyphs"]
    end

    subgraph "After beta.289 — monotonic pageLayoutVersion"
        B
    end
Loading

Comments Outside Diff (1)

  1. bun.lock, line 3474 (link)

    P2 opentype.js major-version jump as a transitive dependency

    @xterm/addon-ligatures@0.11.0-beta.289 now declares "opentype.js": "^2.0.0" (up from ^0.8.0) and "lru-cache": "^11.3.6" (up from ^6.0.0). Both are major-version upgrades in the addon's own dependency list, visible in the lock file. Since typecheck is green and the addon's API is unchanged from the application side this is unlikely to be an issue, but if ligature rendering behaves differently after this update (e.g. a font that rendered ligatures before no longer does), the opentype.js 2.x migration is the first place to look.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: bun.lock
    Line: 3474
    
    Comment:
    **`opentype.js` major-version jump as a transitive dependency**
    
    `@xterm/addon-ligatures@0.11.0-beta.289` now declares `"opentype.js": "^2.0.0"` (up from `^0.8.0`) and `"lru-cache": "^11.3.6"` (up from `^6.0.0`). Both are major-version upgrades in the addon's own dependency list, visible in the lock file. Since typecheck is green and the addon's API is unchanged from the application side this is unlikely to be an issue, but if ligature rendering behaves differently after this update (e.g. a font that rendered ligatures before no longer does), the `opentype.js` 2.x migration is the first place to look.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
bunfig.toml:8-20
**Temporary exclusion needs a follow-up to be removed**

`minimumReleaseAgeExcludes` bypasses the 3-day supply-chain gate and the comment marks it safe to remove after 2026-07-16 — but there is nothing enforcing that cleanup (no CI check, no lint rule, no expiry mechanism). Because `exact = true` already pins these packages, the exclusion is low-risk to leave behind, but it does permanently widen the gate for the entire `@xterm/*` scope for anyone who runs `bun install` with version resolution in the future. A follow-up PR or a TODO ticket to remove these lines after 2026-07-16 would ensure it doesn't linger.

### Issue 2 of 2
bun.lock:3474
**`opentype.js` major-version jump as a transitive dependency**

`@xterm/addon-ligatures@0.11.0-beta.289` now declares `"opentype.js": "^2.0.0"` (up from `^0.8.0`) and `"lru-cache": "^11.3.6"` (up from `^6.0.0`). Both are major-version upgrades in the addon's own dependency list, visible in the lock file. Since typecheck is green and the addon's API is unchanged from the application side this is unlikely to be an issue, but if ligature rendering behaves differently after this update (e.g. a font that rendered ligatures before no longer does), the `opentype.js` 2.x migration is the first place to look.

Reviews (1): Last reviewed commit: "fix(desktop,web): bump @xterm/* to beta...." | Re-trigger Greptile

Comment thread bunfig.toml
Comment on lines +8 to +20
minimumReleaseAgeExcludes = [
"@xterm/xterm",
"@xterm/headless",
"@xterm/addon-clipboard",
"@xterm/addon-fit",
"@xterm/addon-image",
"@xterm/addon-ligatures",
"@xterm/addon-progress",
"@xterm/addon-search",
"@xterm/addon-serialize",
"@xterm/addon-unicode11",
"@xterm/addon-webgl",
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Temporary exclusion needs a follow-up to be removed

minimumReleaseAgeExcludes bypasses the 3-day supply-chain gate and the comment marks it safe to remove after 2026-07-16 — but there is nothing enforcing that cleanup (no CI check, no lint rule, no expiry mechanism). Because exact = true already pins these packages, the exclusion is low-risk to leave behind, but it does permanently widen the gate for the entire @xterm/* scope for anyone who runs bun install with version resolution in the future. A follow-up PR or a TODO ticket to remove these lines after 2026-07-16 would ensure it doesn't linger.

Prompt To Fix With AI
This is a comment left during a code review.
Path: bunfig.toml
Line: 8-20

Comment:
**Temporary exclusion needs a follow-up to be removed**

`minimumReleaseAgeExcludes` bypasses the 3-day supply-chain gate and the comment marks it safe to remove after 2026-07-16 — but there is nothing enforcing that cleanup (no CI check, no lint rule, no expiry mechanism). Because `exact = true` already pins these packages, the exclusion is low-risk to leave behind, but it does permanently widen the gate for the entire `@xterm/*` scope for anyone who runs `bun install` with version resolution in the future. A follow-up PR or a TODO ticket to remove these lines after 2026-07-16 would ensure it doesn't linger.

How can I resolve this? If you propose a fix, please make it concise.

@github-actions

github-actions Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

Architecture diagram
sequenceDiagram
    participant TA as "Terminal A (Active pane)"
    participant TB as "Terminal B (Parked/reused pane)"
    participant Atlas as "Shared Glyph Atlas"
    participant RA as "WebGL Renderer A"
    participant RB as "WebGL Renderer B"

    Note over TA,TB: Same font/theme/DPR -> single WebGL texture atlas

    TA->>Atlas: glyph churn triggers atlas page merge
    Atlas->>Atlas: CHANGED: increment pageLayoutVersion (monotonic, no longer consume-once flag)

    TA->>RA: beginFrame()
    RA->>Atlas: read current pageLayoutVersion
    Atlas-->>RA: version = N
    RA->>RA: cached version < N -> rebuild glyph model (correct texture coordinates)

    TB-->>TB: (parked - no render call)

    Note over TA,TB: Later - user switches to Terminal B

    TB->>RB: beginFrame()
    RB->>Atlas: read current pageLayoutVersion
    Atlas-->>RB: version = N
    RB->>RB: cached version < N -> rebuild glyph model (correct texture coordinates)

    Note over RA,RB: Both renderers retrieve updated atlas coordinates: no more stale texture reads
Loading

Re-trigger cubic

… build

Its beta.289 bundle inlines opentype.js 2.x, which imports
node:diagnostics_channel — vite externalizes node builtins in the renderer
build and fails on the named import. The atlas fix doesn't touch this addon.
@AviPeltz

Copy link
Copy Markdown
Collaborator Author

CI Build failure root-caused and fixed in fbb89b9: @xterm/addon-ligatures@0.11.0-beta.289 inlines opentype.js 2.x, which imports node:diagnostics_channel — vite externalizes node builtins in the renderer bundle and fails on the named import ("channel" is not exported by "__vite-browser-external"). Held that one addon at beta.220 (peer range ^6.1.0-beta.220 is satisfied by core beta.289; the atlas fix is in core + addon-webgl, not ligatures). This also sidesteps the transitive opentype.js 0.8→2.0 ligature-rendering risk Greptile flagged. Desktop build verified locally with the exact CI command.

This branch was previously deployed

1 inactive deployment
preview — fbb89b94 Deployed Jul 15, 2026 by AviPeltz via Deploy API #6541
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant